package genetic.individual;

import genetic.interfaces.Individual;

import java.util.Random;

public abstract class MarioIndividualAbstract<Fitness extends Comparable<Fitness>> implements Individual<Integer, Fitness> {
	protected Integer[]   genes;
	protected Fitness fitness;
	private   int     supLimit;
	private   boolean changed;

	public MarioIndividualAbstract(int numberOfGenes, int supLimit, boolean randomStart){
		this.supLimit = supLimit;
		genes   = new Integer[numberOfGenes];
		changed = true;
		if(randomStart){
			Random randomGenerator = new Random();
			for (int i = 0; i < genes.length; i++) {
				genes[i] = randomGenerator.nextInt(this.supLimit + 1);
			}
		}else{
			for (int i = 0; i < genes.length; i++) {
				genes[i] = 0;
			}
		}
	}
	
	protected MarioIndividualAbstract(MarioIndividualAbstract<Fitness> individual){
		supLimit = individual.supLimit;
		genes    = individual.genes.clone();
		changed  = individual.changed;
		fitness  = individual.copyFitness(individual.fitness);
	}
	
	public int getNumberOfGenes(){
		return genes.length;
	}

	public Integer getGene(int pos){
		return new Integer(genes[pos]);
	}
	
	public Integer[] getGenes(){
		Integer[] arr = new Integer[genes.length];
		System.arraycopy(genes, 0, arr, 0, genes.length);
		return arr;
	}

	public void setGene(int pos, Integer gene){
		if(gene > supLimit)
			genes[pos] = supLimit;
		else if(gene < 0)
			genes[pos] = 0;
		else
			genes[pos] = gene;
		changed = true;
	}


	public Fitness eval(){
		if(changed){
			fitness = evalImplementation();
			changed = false;
		}
		return copyFitness(fitness);
	}
	
	protected abstract Fitness evalImplementation();
	protected abstract Fitness copyFitness(Fitness fitness);
}
